package com.guosen.zebra.framework.starter.xxl.job.autoconfigure;

import com.guosen.zebra.framework.starter.xxl.job.config.XxlJobConfig;
import com.guosen.zebra.framework.starter.xxl.job.util.ZebraXxlJobInetUtils;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * XXL Job 自动装配类
 */
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(XxlJobConfig.class)
public class XxlJobAutoConfiguration {

    /**
     * 构造 XxlJob 执行器 Bean
     * @see <a href="https://github.com/xuxueli/xxl-job/blob/master/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/XxlJobConfig.java">参考 xxl-job-executor-sample-springboot 下的 XxlJobConfig</a>
     * @param xxlJobConfig XXL Job 配置类
     * @return XxlJob 执行器 Bean
     */
    @Bean
    public XxlJobSpringExecutor xxlJobExecutor(XxlJobConfig xxlJobConfig) {
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(xxlJobConfig.getAdminAddresses());
        xxlJobSpringExecutor.setAppname(xxlJobConfig.getAppName());
        xxlJobSpringExecutor.setAddress(xxlJobConfig.getAddress());
        xxlJobSpringExecutor.setIp(getIp(xxlJobConfig));
        xxlJobSpringExecutor.setPort(xxlJobConfig.getPort());
        xxlJobSpringExecutor.setAccessToken(xxlJobConfig.getAccessToken());
        xxlJobSpringExecutor.setLogPath(xxlJobConfig.getLogPath());
        xxlJobSpringExecutor.setLogRetentionDays(xxlJobConfig.getLogRetentionDays());
        return xxlJobSpringExecutor;
    }

    /**
     * 优先取 xxl.job.executor.ip的配置值， 如果为空则取第一个非环回地址
     * @param xxlJobConfig XXL Job 配置类
     * @return 注册ip
     */
    private String getIp(XxlJobConfig xxlJobConfig) {
        String ip = xxlJobConfig.getIp();
        List<String> ignoredInterfaces = xxlJobConfig.getIgnoredInterfaces();
        List<String> preferredNetworks = xxlJobConfig.getPreferredNetworks();
        return isUseXxlJobConfigIp(ip, ignoredInterfaces, preferredNetworks)
                ? ip : ZebraXxlJobInetUtils.findFirstNonLoopbackAddress(ignoredInterfaces, preferredNetworks);
    }

    /**
     * 是否使用配置的注册ip
     * @param ip xxl.job.executor.ip 配置值
     * @param ignoredInterfaces 将被忽略的网络接口的正则表达式列表
     * @param preferredNetworks 首选网络地址的正则表达式列表
     * @return 是否使用
     */
    private boolean isUseXxlJobConfigIp(String ip, List<String> ignoredInterfaces, List<String> preferredNetworks) {
        return StringUtils.hasLength(ip) || (ignoredInterfaces.isEmpty() && preferredNetworks.isEmpty());
    }
}
